﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Media;
using DeepEarth.Map.Core;
using DeepEarth.Map.Core.Tiling;

namespace DeepEarth.Map.TileSources
{
	public class MapServerMapTileSource : BaseTileSource
	{
		static class Default
		{
			internal const string Server = @"http://mercury:81/cgi-bin/mapserv.exe";
			internal const string MapFile = @"map=/Docs/nusphere/wms/agdat.map";
			internal const string Layers = @"layers=imagery";
			//internal static string Parameters = @"mode=tile&tilemode=gmap&tile={0}+{1}+{2}";   //Google Tiles
			internal const string Parameters = @"mode=tile&tilemode=ve&tile={0}";			     //Bing Tiles
		}

		private const int DefaultMaxZoomLevel = 20;
		private const int DefaultTileSize = 256;
		//private const string DefaultTilePath = @"http://mercury:81/cgi-bin/mapserv.exe?map=/Docs/nusphere/wms/agdat.map&layers=imagery&mode=tile&tilemode=gmap&tile={0}+{1}+{2}";

		public string TilePath { get; set; }

		public DateTime? DateMap {get; set;}

		//Constructor Called by XAML instanciation; Wait for MapMode to be set to initialize services
		public MapServerMapTileSource()
			: base(MapServerTileSourceFactory.GoogleMap, (int)Math.Pow(2, DefaultMaxZoomLevel) * DefaultTileSize,
				   (int)Math.Pow(2, DefaultMaxZoomLevel) * DefaultTileSize,
				   DefaultTileSize,
				   DefaultTileSize,
					0)
		{
			TilePath = Default.Server + "?" +
					   Default.MapFile + "&" +
					   Default.Layers + "&" +
					   Default.Parameters;
		}


		public MapServerMapTileSource(string Url)
			: this()
		{
			if (!string.IsNullOrEmpty(Url))
				TilePath = Url;
		}


		protected override void GetTileLayers(int tileLevel, int tilePositionX, int tilePositionY, IList<object> tileImageLayerSources)
		{
			int zoom = tileLevel-8;
			if (zoom > 0)
			{
				//string url = string.Format(TilePath, tilePositionX, tilePositionY, zoom);						//Google Tiles
				string url = string.Format(TilePath, TileXYToQuadKey(tilePositionX, tilePositionY, zoom));		//Bing Tiles
				tileImageLayerSources.Add(new Uri(url));
			}
		}

		private static string TileXYToQuadKey(int tileX, int tileY, int levelOfDetail)
		{
			var quadKey = new StringBuilder();
			for (int i = levelOfDetail; i > 0; i--)
			{
				char digit = '0';
				int mask = 1 << (i - 1);
				if ((tileX & mask) != 0)
				{
					digit++;
				}
				if ((tileY & mask) != 0)
				{
					digit++;
					digit++;
				}
				quadKey.Append(digit);
			}
			return quadKey.ToString();
		}
	}
}